package com.suredy.app.porject.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Service;

import com.suredy.app.porject.constants.ContractStatus;
import com.suredy.app.porject.constants.ContractType;
import com.suredy.app.porject.constants.FlowStatus;
import com.suredy.app.porject.model.Contract;
import com.suredy.core.service.BaseSrvWithEntity;

@Service
public class ContractSrv extends BaseSrvWithEntity<Contract> {

	@Override
	public DetachedCriteria getDc(Contract t) {
		DetachedCriteria dc = super.getDc(t);

		if (t == null)
			return dc;

		if (!StringUtils.isBlank(t.getId())) {
			dc.add(Restrictions.eq("id", t.getId()));
		}
		if (!StringUtils.isBlank(t.getName())) {
			dc.add(Restrictions.like("name", t.getName(), MatchMode.ANYWHERE));
		}
		if (!StringUtils.isBlank(t.getNo())) {
			dc.add(Restrictions.like("no", t.getNo(), MatchMode.ANYWHERE));
		}
		if (!StringUtils.isBlank(t.getCompanyA())) {
			dc.add(Restrictions.like("companyA", t.getCompanyA(), MatchMode.ANYWHERE));
		}
		if (!StringUtils.isBlank(t.getCompanyB())) {
			dc.add(Restrictions.like("companyB", t.getCompanyB(), MatchMode.ANYWHERE));
		}
		if (!StringUtils.isBlank(t.getManager())) {
			dc.add(Restrictions.like("manager", t.getManager(), MatchMode.ANYWHERE));
		}
		if (t.getType() != null) {
			dc.add(Restrictions.eq("type", t.getType()));
		}
		if (t.getStatus() != null) {
			dc.add(Restrictions.eq("status", t.getStatus()));
		}
		if (t.getBid() != null) {
			dc.add(Restrictions.eq("bid", t.getBid()));
		}
		if (t.getParent() != null) {
			dc.add(Restrictions.eq("parent", t.getParent()));
		}
		if (t.getFlowStatus() != null) {
			dc.add(Restrictions.eq("flowStatus", t.getFlowStatus()));
		}
		if (t.getBjTimeStart() != null) {
			dc.add(Restrictions.ge("bjTime", t.getBjTimeStart()));
		}
		if (t.getBjTimeEnd() != null) {
			dc.add(Restrictions.le("bjTime", t.getBjTimeEnd()));
		}
		if (t.getContractDays() != null) {
			dc.add(Restrictions.eq("contractDays", t.getContractDays()));
		}

		if (t.getContractStart() != null && t.getContractEnd() != null) {
			dc.add(Restrictions.or(Restrictions.between("contractStart", t.getContractStart(), t.getContractEnd()), Restrictions.between("contractEnd", t.getContractStart(), t.getContractEnd())));
		} else if (t.getContractStart() != null) {
			dc.add(Restrictions.ge("contractStart", t.getContractStart()));
		} else if (t.getContractEnd() != null) {
			dc.add(Restrictions.le("contractEnd", t.getContractEnd()));
		}

		return dc;
	}

	@SuppressWarnings("unchecked")
	public Map<String, Long> getContractTotal(Date yearStart, Date yearEnd, ContractType... types) {
		List<Object[]> data = null;

		List<Object> param = new ArrayList<Object>();
		String ql;

		if (types != null && types.length > 0) {
			ql = "SELECT T.flowStatus, COUNT(T.id) FROM Contract T WHERE T.type in (:in) {year} GROUP BY T.flowStatus";

			String tmp = "";
			for (int i = 0; i < types.length; i++) {
				if (!StringUtils.isBlank(tmp))
					tmp += ",";

				tmp += "?";

				param.add(types[i]);
			}

			ql = ql.replace(":in", tmp);
		} else {
			ql = "SELECT T.flowStatus, COUNT(T.id) FROM Contract T WHERE 1=1 {year} GROUP BY T.flowStatus";
		}

		String yearStr = "";
		if (yearStart != null) {
			yearStr = " signDate >= ?";
			param.add(yearStart);
		}
		if (yearEnd != null) {
			if (!StringUtils.isBlank(yearStr))
				yearStr += " AND";

			yearStr += " signDate <= ?";
			param.add(yearEnd);
		}

		if (StringUtils.isBlank(yearStr)) {
			ql = ql.replace("{year}", "");
		} else {
			ql = ql.replace("{year}", " AND " + yearStr);
		}

		if (param.isEmpty())
			data = (List<Object[]>) this.readByQL(ql);
		else
			data = (List<Object[]>) this.readByQL(ql, param.toArray());

		Map<String, Long> ret = new LinkedHashMap<String, Long>();
		ret.put("签订中", 0L);
		ret.put("已签订", 0L);

		if (data != null)
			for (Object[] d : data) {
				if (d == null || d.length != 2)
					continue;

				FlowStatus status = (FlowStatus) d[0];
				long count = (long) d[1];

				String key = "已签订";

				switch (status) {
					case FS2000_CONTRACT_TO_CREATE:
						// 签订中
						key = "签订中";
						break;
				}

				ret.put(key, ret.get(key) + count);
			}

		return ret;
	}

	@SuppressWarnings("unchecked")
	public Map<String, Long> getContractStatusTotal(Date yearStart, Date yearEnd, ContractType... types) {
		List<Object[]> data = null;

		List<Object> param = new ArrayList<Object>();
		String ql;

		if (types != null && types.length > 0) {
			ql = "SELECT T.status, COUNT(T.id) FROM Contract T WHERE T.type in (:in) {year} GROUP BY T.status";

			String tmp = "";
			for (int i = 0; i < types.length; i++) {
				if (!StringUtils.isBlank(tmp))
					tmp += ",";

				tmp += "?";

				param.add(types[i]);
			}

			ql = ql.replace(":in", tmp);
		} else {
			ql = "SELECT T.flowStatus, COUNT(T.id) FROM Contract WHERE 1=1 {year} T GROUP BY T.flowStatus";
		}

		String yearStr = "";
		if (yearStart != null) {
			yearStr = " signDate >= ?";
			param.add(yearStart);
		}
		if (yearEnd != null) {
			if (!StringUtils.isBlank(yearStr))
				yearStr += " AND";

			yearStr += " signDate <= ?";
			param.add(yearEnd);
		}

		if (StringUtils.isBlank(yearStr)) {
			ql = ql.replace("{year}", "");
		} else {
			ql = ql.replace("{year}", " AND " + yearStr);
		}

		if (param.isEmpty())
			data = (List<Object[]>) this.readByQL(ql);
		else
			data = (List<Object[]>) this.readByQL(ql, param.toArray());

		Map<String, Long> ret = new LinkedHashMap<String, Long>();
		ret.put(ContractStatus.WAIT.getValue(), 0L);
		ret.put(ContractStatus.START.getValue(), 0L);
		ret.put(ContractStatus.FINISH.getValue(), 0L);
		ret.put(ContractStatus.COMPLETED.getValue(), 0L);
		ret.put(ContractStatus.SUSPEND.getValue(), 0L);
		ret.put(ContractStatus.SHUTDOWN.getValue(), 0L);

		if (data != null)
			for (Object[] d : data) {
				if (d == null || d.length != 2)
					continue;

				ContractStatus status = (ContractStatus) d[0];
				long count = (long) d[1];

				String key = status.getValue();

				ret.put(key, ret.get(key) + count);
			}

		return ret;
	}

	public ContractType getTypeBy(String id) {
		if (StringUtils.isBlank(id))
			return null;

		String ql = "SELECT T.type FROM Contract T WHERE T.id = ?";

		return (ContractType) this.readSingleByQL(ql, id);
	}

	/**
	 * 获取父合同的id
	 * 
	 * @param id
	 * @return
	 */
	public String getParentId(String id) {
		if (StringUtils.isBlank(id))
			return null;

		String ql = "SELECT T.parent.id FROM Contract T WHERE T.id=?";

		return (String) this.readSingleByQL(ql, id);
	}

}
